package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.TsCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private AlbumAttributeValueMapper albumAttributeValueMapper;
	@Autowired
	private AlbumStatMapper albumStatMapper;
	@Autowired
	private RabbitService rabbitService;
	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private RedissonClient redissonClient;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
//		生成一个新的AlbumInfo对象 去封装新的数据
		AlbumInfo albumInfo = new AlbumInfo();
//		调用beanUtils工具类去拷贝数据
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
//		将用户id封装到albumInfo对象中
		albumInfo.setUserId(userId);
//		判断专辑支付类型
//		如果不是免费的就将免费试听的集数设置为5
		if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())){
			albumInfo.setTracksForFree(5);
		}
//		设置专辑的初始状态为通过
		albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
//		调用对应mapper将数据插入
		albumInfoMapper.insert(albumInfo);
//		插入对应的albumAttributeValue
//		获取出albumAttributeValue列表
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
//		遍历列表
		for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
//			创建一个新的albumAttributeValue对象
			AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
//			使用工具类去拷贝属性
			BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);
//			从上面插入的albumInfo中找到albumid插入到albumAttributeValue中
			albumAttributeValue.setAlbumId(albumInfo.getId());
//			将数据插入到albumAttributeValue中
			albumAttributeValueMapper.insert(albumAttributeValue);
		}
//		插入对应的album_stat表数据
		inseterAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_PLAY);
		inseterAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_SUBSCRIBE);
		inseterAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_BROWSE);
		inseterAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_COMMENT);
	}
//	封装对应的album_stat
	public void inseterAlbumStat(Long albumId,String statType){
		//		生成一个随机数
		Random rd = new Random();
//		创建一个新的AlbumStat对象
		AlbumStat albumStat = new AlbumStat();
//		进行赋值
		albumStat.setAlbumId(albumId);
		albumStat.setStatType(statType);
		albumStat.setStatNum(rd.nextInt(100000));
//		赋值后插入
		albumStatMapper.insert(albumStat);
	}

	@Override
	public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> page, AlbumInfoQuery albumInfoQuery) {
		return albumInfoMapper.findUserAlbumPage(page,albumInfoQuery);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeAlbumInfo(Long albumId) {
//		删除albumInfo中的数据
		this.remove(new LambdaQueryWrapper<AlbumInfo>().eq(AlbumInfo::getId,albumId));
//		删除albumstat中的数据
		albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId,albumId));
//		删除album_attribute_value中的数据
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
//		删除之后直接发送延迟消息去调用方法下架
		rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,MqConst.QUEUE_ALBUM_LOWER);
	}

	/**
	 * 重写获取相册信息方法
	 * 首先尝试从Redis中获取相册信息，如果获取失败，则使用Redisson的分布式锁防止缓存击穿
	 * 如果锁获取成功，再次尝试从Redis中获取相册信息，如果仍然获取失败，则从数据库中获取信息
	 * 并将其存入Redis中，以供下次快速访问
	 *
	 * @param albumId 相册ID
	 * @return AlbumInfo对象，包含相册信息如果相册不存在，则返回一个空的AlbumInfo对象
	 */
	@TsCache(prefix = RedisConstant.ALBUM_INFO_PREFIX)
	@Override
	public AlbumInfo getAlbumInfo(Long albumId) {
//	    // 构造Redis键
//	    String redisKey = RedisConstant.ALBUM_INFO_PREFIX+albumId;
//	    try {
//	        // 尝试从Redis中获取相册信息
//	        AlbumInfo albuminfo = (AlbumInfo) redisTemplate.opsForValue().get(redisKey);
//	        if (albuminfo!=null){
//	            // 如果获取成功，直接返回相册信息
//	            return albuminfo;
//	        }else {
//	            // 构造锁键，用于防止缓存击穿
//	            String LockKey = RedisConstant.ALBUM_LOCK_SUFFIX+albumId;
//	            RLock lock = redissonClient.getLock(LockKey);
//	            try {
//	                // 加锁，防止多线程环境下同时更新缓存
//	                lock.lock();
//	                // 再次尝试从Redis中获取相册信息，防止在等待锁的过程中其他线程已经更新了缓存
//	                albuminfo = (AlbumInfo) redisTemplate.opsForValue().get(redisKey);
//	                if (null !=albuminfo){
//	                    // 如果获取成功，直接返回相册信息
//	                    return albuminfo;
//	                }
//	                // 从数据库中获取相册信息
//	                albuminfo = getInfo(albumId);
//	                if (albuminfo!=null){
//	                    // 如果获取成功，将其存入Redis中，并返回相册信息
//	                    redisTemplate.opsForValue().set(redisKey,albuminfo);
//	                    return albuminfo;
//	                }else {
//	                    // 如果获取失败，向Redis中存入一个空的相册信息对象，防止缓存击穿
//	                    redisTemplate.opsForValue().set(redisKey,new AlbumInfo(),1, TimeUnit.MINUTES);
//	                    return new AlbumInfo();
//	                }
//	            } finally {
//	                // 释放锁
//	                lock.unlock();
//	            }
//	        }
//	    } catch (Exception e) {
//	        // 异常处理，打印错误信息
//	        e.getMessage();
//	    }
//	    // 如果以上步骤都失败，最后尝试从数据库中获取相册信息
	    return getInfo(albumId);
	}

//	查询数据库，根据专辑id获取专辑数据
	public AlbumInfo getInfo(Long albumId) {
		//		获取数据
		AlbumInfo albumInfo = this.getById(albumId);
		if (albumInfo!=null){
//			根据专辑id获取专辑的属性值
			List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
			albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);
		}
		return albumInfo;
	}

	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {
//		添加分页条件
		Page<AlbumInfo> page = new Page<>(1, 30);
//		设置新的LambdaQueryWrapper对象,并添加指定条件
		LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<AlbumInfo>().select(AlbumInfo::getId, AlbumInfo::getAlbumTitle).eq(AlbumInfo::getUserId, userId).orderByDesc(AlbumInfo::getId);
//		调用selectPage方法去获取分页中的数据,再通过getRecords方法获取列表数据并且返回
		return albumInfoMapper.selectPage(page, queryWrapper).getRecords();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateAlbumInfo(AlbumInfoVo albumInfoVo, Long albumId) {
//		生成一个新的albumInfo对象
		AlbumInfo albumInfo = new AlbumInfo();
//		属性拷贝
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
//        将id传到albumInfo中
        albumInfo.setId(albumId);
//		更新albumInfo专辑数据
		this.updateById(albumInfo);
//		先删除之前的标签值
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
//		获取所有的属性值
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
//		如果不为空
		if (!CollectionUtils.isEmpty(albumAttributeValueVoList)){
//			遍历将其加入数据库中
			for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
//				生成一个新的AlbumAttributeValue对象
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
//				使用工具类去拷贝属性
				BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);
//				给aibumAttributeValue设置专辑id
				albumAttributeValue.setAlbumId(albumId);
//				插入数据
				albumAttributeValueMapper.insert(albumAttributeValue);
			}
		}
//		判断,如果是公开的话,就发送消息去让消费者上架
		if("1".equals(albumInfo.getIsOpen())){
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER,albumId);
			//        将对应的专辑id上传到布隆过滤器中
			RBloomFilter bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
			bloomFilter.add(albumId);
			log.info("专辑上架成功");
		}else {
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumId);
		}
	}

	@TsCache(prefix = "album:stat:")
	@Override
	public AlbumStatVo getAlbumStat(Long albumId) {
		AlbumStatVo albumStatVo = albumInfoMapper.getAlbumStat(albumId);
		return albumStatVo;
	}
}
